import redis
import json
from typing import Any, Optional, Union
from datetime import timedelta

from app.core.config import settings


class RedisCache:
    """Redis缓存工具类"""

    def __init__(self):
        self.redis_client = redis.Redis(
            host=settings.REDIS_HOST,
            port=settings.REDIS_PORT,
            password=settings.REDIS_PASSWORD,
            db=settings.REDIS_DB,
            decode_responses=True,
            socket_connect_timeout=5,
            socket_timeout=5,
        )

    async def get(self, key: str) -> Optional[Any]:
        """获取缓存值"""
        try:
            value = self.redis_client.get(key)
            if value:
                return json.loads(value)
            return None
        except Exception as e:
            # 日志记录错误
            return None

    async def set(
        self,
        key: str,
        value: Any,
        expire: Optional[Union[int, timedelta]] = None
    ) -> bool:
        """设置缓存值"""
        try:
            json_value = json.dumps(value, ensure_ascii=False)
            if expire:
                if isinstance(expire, timedelta):
                    expire = int(expire.total_seconds())
                return self.redis_client.setex(key, expire, json_value)
            else:
                return self.redis_client.set(key, json_value)
        except Exception as e:
            # 日志记录错误
            return False

    async def delete(self, key: str) -> bool:
        """删除缓存"""
        try:
            return bool(self.redis_client.delete(key))
        except Exception as e:
            # 日志记录错误
            return False

    async def exists(self, key: str) -> bool:
        """检查缓存是否存在"""
        try:
            return bool(self.redis_client.exists(key))
        except Exception as e:
            # 日志记录错误
            return False

    async def expire(self, key: str, seconds: int) -> bool:
        """设置缓存过期时间"""
        try:
            return bool(self.redis_client.expire(key, seconds))
        except Exception as e:
            # 日志记录错误
            return False

    async def ttl(self, key: str) -> int:
        """获取缓存剩余生存时间"""
        try:
            return self.redis_client.ttl(key)
        except Exception as e:
            # 日志记录错误
            return -1

    async def keys(self, pattern: str = "*") -> list:
        """获取匹配的键列表"""
        try:
            return self.redis_client.keys(pattern)
        except Exception as e:
            # 日志记录错误
            return []

    async def flushdb(self) -> bool:
        """清空当前数据库"""
        try:
            return self.redis_client.flushdb()
        except Exception as e:
            # 日志记录错误
            return False

    async def incr(self, key: str, amount: int = 1) -> int:
        """递增计数器"""
        try:
            return self.redis_client.incr(key, amount)
        except Exception as e:
            # 日志记录错误
            return 0

    async def decr(self, key: str, amount: int = 1) -> int:
        """递减计数器"""
        try:
            return self.redis_client.decr(key, amount)
        except Exception as e:
            # 日志记录错误
            return 0

    # 哈希操作
    async def hget(self, name: str, key: str) -> Optional[Any]:
        """获取哈希字段值"""
        try:
            value = self.redis_client.hget(name, key)
            if value:
                return json.loads(value)
            return None
        except Exception as e:
            return None

    async def hset(self, name: str, key: str, value: Any) -> bool:
        """设置哈希字段值"""
        try:
            json_value = json.dumps(value, ensure_ascii=False)
            return bool(self.redis_client.hset(name, key, json_value))
        except Exception as e:
            return False

    async def hgetall(self, name: str) -> dict:
        """获取哈希所有字段"""
        try:
            result = self.redis_client.hgetall(name)
            return {k: json.loads(v) for k, v in result.items()}
        except Exception as e:
            return {}

    async def hdel(self, name: str, *keys) -> int:
        """删除哈希字段"""
        try:
            return self.redis_client.hdel(name, *keys)
        except Exception as e:
            return 0

    # 列表操作
    async def lpush(self, name: str, *values) -> int:
        """从左侧推入列表"""
        try:
            json_values = [json.dumps(v, ensure_ascii=False) for v in values]
            return self.redis_client.lpush(name, *json_values)
        except Exception as e:
            return 0

    async def rpush(self, name: str, *values) -> int:
        """从右侧推入列表"""
        try:
            json_values = [json.dumps(v, ensure_ascii=False) for v in values]
            return self.redis_client.rpush(name, *json_values)
        except Exception as e:
            return 0

    async def lpop(self, name: str) -> Optional[Any]:
        """从左侧弹出列表元素"""
        try:
            value = self.redis_client.lpop(name)
            if value:
                return json.loads(value)
            return None
        except Exception as e:
            return None

    async def rpop(self, name: str) -> Optional[Any]:
        """从右侧弹出列表元素"""
        try:
            value = self.redis_client.rpop(name)
            if value:
                return json.loads(value)
            return None
        except Exception as e:
            return None

    async def lrange(self, name: str, start: int = 0, end: int = -1) -> list:
        """获取列表范围元素"""
        try:
            values = self.redis_client.lrange(name, start, end)
            return [json.loads(v) for v in values]
        except Exception as e:
            return []


# 创建缓存实例
cache = RedisCache()